package com.cm.kits;

import java.security.SecureRandom;

/**
 * 随机数工具，提供生成随机数字和随机字符串功能
 * <p>
 * 本工具类中的方法都可以使用 Apace Common-lang3 中的工具替代，不过在简单环境下，建议使用本工具类
 *
 * @author LWang 2023.01.20
 * @see org.apache.commons.lang3.RandomUtils
 * @see org.apache.commons.lang3.RandomStringUtils
 * @since 1.0.0
 */
public final class RandomKits {

    private RandomKits() {

    }

    private static final SecureRandom SECURE_RANDOM = new SecureRandom();

    private static final char[] CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*-_=+".toCharArray();

    /**
     * 获取一个随机整数
     *
     * @return 随机数
     */
    public static int nextInt() {
        return SECURE_RANDOM.nextInt();
    }

    /**
     * 获取一个随机整数
     *
     * @param bound 随机数范围上限
     * @return 随机数
     */
    public static int nextInt(int bound) {
        return SECURE_RANDOM.nextInt(bound);
    }

    /**
     * 获取一个随机整数
     *
     * @param origin 随机数范围下限
     * @param bound  随机数范围上限
     * @return 随机数
     */
    public static int nextInt(int origin, int bound) {
        return SECURE_RANDOM.nextInt(origin, bound);
    }

    /**
     * 获取一个随机长整数
     *
     * @return 随机数
     */
    public static long nextLong() {
        return SECURE_RANDOM.nextLong();
    }

    /**
     * 获取一个随机长整数
     *
     * @param bound 随机数范围上限
     * @return 随机数
     */
    public static long nextLong(long bound) {
        return SECURE_RANDOM.nextLong(bound);
    }

    /**
     * 获取一个随机长整数
     *
     * @param origin 随机数范围下限
     * @param bound  随机数范围上限
     * @return 随机数
     */
    public static long nextLong(long origin, long bound) {
        return SECURE_RANDOM.nextLong(origin, bound);
    }


    /**
     * 获取一个随机单精浮点数
     *
     * @return 随机数
     */
    public static float nextFloat() {
        return SECURE_RANDOM.nextFloat();
    }

    /**
     * 获取一个随机单精浮点数
     *
     * @param bound 随机数范围上限
     * @return 随机数
     */
    public static float nextFloat(float bound) {
        return SECURE_RANDOM.nextFloat(bound);
    }

    /**
     * 获取一个随机单精浮点数
     *
     * @param origin 随机数范围下限
     * @param bound  随机数范围上限
     * @return 随机数
     */
    public static float nextFloat(float origin, float bound) {
        return SECURE_RANDOM.nextFloat(origin, bound);
    }

    /**
     * 获取一个随机双精浮点数
     *
     * @return 随机数
     */
    public static double nextDouble() {
        return SECURE_RANDOM.nextDouble();
    }

    /**
     * 获取一个随机双精浮点数
     *
     * @param bound 随机数范围上限
     * @return 随机数
     */
    public static double nextDouble(double bound) {
        return SECURE_RANDOM.nextDouble(bound);
    }

    /**
     * 获取一个随机双精浮点数
     *
     * @param origin 随机数范围下限
     * @param bound  随机数范围上限
     * @return 随机数
     */
    public static double nextDouble(double origin, double bound) {
        return SECURE_RANDOM.nextDouble(origin, bound);
    }

    /**
     * 生成一个随机字符串，使用数字、字母和常用符号组成，也可以使用 Apache Common-lang3 中的 RandomStringUtils 类中的对应方法，不过那个考虑的情况太多，
     * 在使用要求不复杂的情况下，使用本方法即可
     *
     * @param length 随机字符串长度
     * @return 随机字符串
     * @see org.apache.commons.lang3.RandomStringUtils
     */
    public static String nextString(final int length) {
        if (length <= 0) {
            throw new IllegalArgumentException("生成随机字符串长度必须大于零！");
        }
        StringBuilder builder = new StringBuilder(length);
        int bound = CHARS.length;
        int count = length;
        while (count-- != 0) {
            builder.append(CHARS[nextInt(bound)]);
        }
        return builder.toString();
    }
}
